
/**
 * 	分割画像による拡大表示ライブラリ
 *	@Class Ext.ux.ZoomMap
 *	@extends Ext.util.Observable
 *
 *	@version 1.0
 *	@author Naohiro Tateishi n-tateishi@prod.sus4.co.jp
 *　
 *	@constructor
 *	@param elId String
 *	@param config Object
 *
 *　	//Sample
 *
 * 	Ext.onReady(function() {
 *		new Ext.ux.ZoomMap( 'map', {
 *		colMax : [6,11,22,44,88],
 *		rowMax : [2,4,7,14,28],
 *		clipSize : 200,
 *		startPos : {x:-578,y:-35},
 *		fileName : 'expressboad',
 *		dataDir : ["zm","zoom","zoom1","zoom2","zoom3"]
 *		});
 *	});
 */



Ext.ns('Ext.ux');

Ext.ux.ZoomMap = Ext.extend(Ext.util.Observable,
{
	colMax : [],
	rowMax : [],
	clipSize : 100,
	zoomLevel : 1,
	startPos : {x:0,y:0},
	fileName : 'imagefile',
	fileExt : "jpg",
	dataDir : [],
	navi: true,
	
	setColRow:function()
	{
		Ext.ux.ZoomMap.colrow = new Array(this.colMax[this.zoomLevel]);
		for(var i = 0; i < Ext.ux.ZoomMap.colrow.length; i++) Ext.ux.ZoomMap.colrow[i] = new Array(this.rowMax[this.zoomLevel]);
		Ext.ux.ZoomMap.isLoadedLine = {col:0,row:0};
	},
	
	constructor: function(elId, config)
	{
		config = config || {};
		Ext.apply(this, config);
		this.setColRow();
		
		Ext.ux.ZoomMap.superclass.constructor.call(this, config);
		this.el = Ext.get(elId);
		
		this.initMarkup();
		this.initEvent();	
		this.setPos(this.clipBase, -this.startPos.x, -this.startPos.y);
		this.setClips(this.clipBase,0,0);
	},

	
	initMarkup: function()
	{
		if(this.navi){
			this.controlBase = this.el.insertFirst(
			{
				id: 'ext-zoommap-controlBase',
				tag: 'div'
			});
			this.resetBtn = this.controlBase.insertFirst(
			{
				id: 'ext-zoommap-resetBtn',
				tag: 'div',
				cls: 'ext-zoommap-Btn'
			});
			this.zoomUp = this.controlBase.insertFirst(
			{
				id: 'ext-zoommap-zUpBtn',
				tag: 'div',
				cls: 'ext-zoommap-Btn'
			});
			this.zoomOut = this.controlBase.insertFirst(
			{
				id: 'ext-zoommap-zOutBtn',
				tag: 'div',
				cls: 'ext-zoommap-Btn'
			});
		}
		
		this.baseClip = this.el.insertFirst(
		{
			id: 'ext-zoommap-frame',
			tag: 'div'
		});
		this.baseClip.setStyle({
			userSelect: 'none',
			overflow: 'hidden',
			cursor: 'pointer',
			position:'relative'
		});
		this.dummyClip = this.baseClip.insertFirst(
		{
			id: 'ext-zoommap-dummyClip',
			tag: 'div'
		});
		this.dummyClip.setStyle({
			position:'relative'
		});
		this.clipBase = this.baseClip.insertFirst(
		{
			id: 'ext-zoommap-clipBase',
			tag: 'div'
		});
		this.clipBase.setStyle({
			whiteSpace:'nowrap'
		});
	},
	
	
	setClips : function(pClip, c, r)
	{
		if(this.getLeftTop().x < 0){
			c = -Math.ceil(this.getLeftTop().x / this.clipSize);
		}
		if(this.getLeftTop().y < 0){
			r = -Math.ceil(this.getLeftTop().y / this.clipSize);
		}
		
		for(var i = r; i < this.rowMax[this.zoomLevel]; i++){
			
			for(var k = c; k < this.colMax[this.zoomLevel]; k++){
				
				if(Ext.ux.ZoomMap.colrow[k][i]) continue;
				if(!this.checkClipPos({col:k,row:0})) break;
				
				var ccc = this.addClip({col:k,row:i});
			}
			
			if(!this.checkClipPos({col:0,row:i+1})) break;
		}
		
		if(k == this.colMax[this.zoomLevel]) k --;
		if(i == this.rowMax[this.zoomLevel]) i --;
			
		this.checkLoadedLine();
	},
	
	
	
	addClip: function(pos)
	{
		Ext.ux.ZoomMap.colrow[pos.col][pos.row] = true;
		
		var clip = this.clipBase.insertFirst(
		{
			tag:'img',
			src:"img/"+this.dataDir[this.zoomLevel]+'/'+this.fileName+'_r'+(pos.row+1)+'_c'+(pos.col+1)+'.'+this.fileExt,
			width:this.clipSize,
			height:this.clipSize
		});
		clip.position("absolute");
		clip.setLeft(pos.col*this.clipSize);
		clip.setTop(pos.row*this.clipSize);
		clip.setStyle({border:'none'});
		return clip;
	},



	checkClipPos: function(pos)
	{
		if(this.getLeftTop().x + pos.col * this.clipSize > this.getFrameWidth()) return false;
		if(this.getLeftTop().y + pos.row * this.clipSize > this.getFrameHeight()) return false;
		return true;
	},
	


	checkLoadedLine: function()
	{
		for(var i = 0; i < this.rowMax[this.zoomLevel]; i++){
			
			for(var k = 0; k < this.colMax[this.zoomLevel]; k++){
				
				var flag = false;
				if(!Ext.ux.ZoomMap.colrow[k][i]) break;
				flag = true;
			}
			
			if(!flag) continue;
			
			Ext.ux.ZoomMap.isLoadedLine.row = i;
		}
		
		for(var i = 0; i < this.colMax[this.zoomLevel]; i++){
			
			for(var k = 0; k < this.rowMax[this.zoomLevel]; k++){
				
				var flag = false;
				if(!Ext.ux.ZoomMap.colrow[i][k]) break;
				flag = true;
			}
			
			if(!flag) continue;
			Ext.ux.ZoomMap.isLoadedLine.col = i;
		}
	},


	
	resetClip: function()
	{
		if(	Ext.ux.ZoomMap.isLoadedLine.col == this.colMax[this.zoomLevel] - 1 &&
			Ext.ux.ZoomMap.isLoadedLine.row == this.rowMax[this.zoomLevel] - 1) return;
		
		var clip = this.clipBase;
		var lt = this.getLeftTop();
		var rd = {	x:lt.x + (Ext.ux.ZoomMap.isLoadedLine.col + 1)*this.clipSize,
					y:lt.y + (Ext.ux.ZoomMap.isLoadedLine.row + 1)*this.clipSize};
		
		if(rd.x < this.getFrameWidth() && Ext.ux.ZoomMap.isLoadedLine.col < this.colMax[this.zoomLevel] - 1){
			this.setClips(clip, 0, 0);
		}
		
		if(rd.y < this.getFrameHeight() && Ext.ux.ZoomMap.isLoadedLine.row < this.rowMax[this.zoomLevel] - 1){
			this.setClips(clip, 0, 0);
		}
	},

	
	
	changeZoom : function(clip, pos, d)
	{
		pos[0] = pos[0] - this.baseClip.getX();
		pos[1] = pos[1] - this.baseClip.getY();
		
		var mpX = pos[0] - this.getLeftTop().x;
		var mpY = pos[1] - this.getLeftTop().y;
		
		var isLevel = this.zoomLevel;
		
		if(d>0)this.zoomLevel ++;
		else this.zoomLevel --;
		
		if(this.zoomLevel >= this.dataDir.length){
			this.zoomLevel = this.dataDir.length - 1;
			return;
		}
		
		if(this.zoomLevel < 0){
			this.zoomLevel = 0;
			return;
		}
		
		if(this.zoomLevel-isLevel < 0){
			mpX = mpX * -0.5;
			mpY = mpY * -0.5;
			var nFlag = true;
		}
		
		this.deleteZoom(clip, mpX, mpY, nFlag);
		
		this.setColRow();
		this.setPos(clip, mpX, mpY);
		this.setClips(clip, 0, 0);
	},


	
	deleteZoom: function(clip, x, y, f)
	{
		var size = this.clipSize * 2;
		if(f) size = this.clipSize / 2;
		
		var dummy = this.dummyClip;
		var els = clip.select('img');
		
		for(var i = 0; i < els.elements.length; i ++){
			dummy.insertFirst(els.elements[i]);
		};
		dummy.setLeft(this.getLeftTop().x);
		dummy.setTop(this.getLeftTop().y);
		
		clip.select('img').remove();
		
		dummy.select('img').fadeOut(
		{
			callback:function(){
				dummy.select('img').remove();
			}
		});
	},
	
	
		
	setPos: function(elm,px,py)
	{
		elm.setLocation(elm.getX()-px, elm.getY()-py);
	},
	

	
	getLeftTop: function()
	{
		if(!Ext.ux.ZoomMap.resetPos) Ext.ux.ZoomMap.resetPos = {x:this.clipBase.getX(), y:this.clipBase.getY()};
		return {x:this.clipBase.getX()-this.baseClip.getX(), y:this.clipBase.getY()-this.baseClip.getY()};
	},
	
	

	getFrameWidth: function()
	{
		return this.baseClip.getWidth();
	},
	

	
	getFrameHeight: function()
	{
		return this.baseClip.getHeight();
	},
	
	
	
	initEvent : function()
	{
		this.baseClip.on('mousedown',function(e,target){
			Ext.ux.ZoomMap.isDown = true;
			Ext.ux.ZoomMap.isPos = e.xy;
		},this,{
			preventDefault:true,
			stopPropagation:true
		});
		this.baseClip.on('mouseenter',function(e,target){
			if(!Ext.ux.ZoomMap.isDown) return;
			Ext.ux.ZoomMap.isPos = e.xy;
		},this,{
			preventDefault:true,
			stopPropagation:true
		});
		var target = window;
		if(Ext.isIE) target = document
		Ext.fly(target).on('mouseup',function(e,target){
			Ext.ux.ZoomMap.isDown = false;
		},this,{
			preventDefault:true,
			stopPropagation:true
		});
		Ext.fly(target).on('mousemove',function(e,target){
			if(!Ext.ux.ZoomMap.isDown) return;
			this.setPos(this.clipBase, Ext.ux.ZoomMap.isPos[0]-e.xy[0], Ext.ux.ZoomMap.isPos[1]-e.xy[1]);
			Ext.ux.ZoomMap.isPos = e.xy;	
			this.resetClip();
		},this,{
			preventDefault:true,
			stopPropagation:true
		});
		this.baseClip.on('dblclick',function(e,target){
			this.changeZoom(this.clipBase, e.xy, 1);
		},this,{
			preventDefault:true,
			stopPropagation:true
		});		
		this.baseClip.on('mousewheel',function(e,target){
			this.changeZoom(this.clipBase, e.xy, e.getWheelDelta());
		},this,{
			preventDefault:true,
			stopPropagation:true
		});
		
		if(this.navi){
			this.zoomUp.on('click',function(e,target){
				this.changeZoom(this.clipBase, [this.getFrameWidth()/2+this.baseClip.getLeft(),this.getFrameHeight()/2+this.baseClip.getTop()], 1);
			},this,{
				preventDefault:true,
				stopPropagation:true
			});			
			this.zoomOut.on('click',function(e,target){
				this.changeZoom(this.clipBase, [this.getFrameWidth()/2+this.baseClip.getLeft(),this.getFrameHeight()/2+this.baseClip.getTop()], -1);
			},this,{
				preventDefault:true,
				stopPropagation:true
			});
			this.resetBtn.on('click',function(e,target){
				this.zoomLevel = 1;
				this.setColRow();
				this.clipBase.select('img').remove();
				this.clipBase.setLocation(Ext.ux.ZoomMap.resetPos.x,Ext.ux.ZoomMap.resetPos.y);
				this.setClips(this.clipBase, 0, 0);
			},this,{
				preventDefault:true,
				stopPropagation:true
			});
		}
	}
});

Ext.ux.ZoomMap.isLoadedLine = {col:0,row:0};
Ext.ux.ZoomMap.isDown = false;
Ext.ux.ZoomMap.isPos = [0,0];
Ext.ux.ZoomMap.resetPos = null;
Ext.ux.ZoomMap.colrow = null;
